/*
 * Copyright 2013-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.denghq.projectbuilder.component.nacos.config;

import com.denghq.projectbuilder.component.config.domain.ConfigClassCollector;
import com.denghq.projectbuilder.component.config.domain.ConfigClassParser;
import com.denghq.projectbuilder.component.nacos.config.client.NacosPropertySourceLocator;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author xiaojing
 */
@Configuration
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigBootstrapConfiguration {

    /**
     * 配置自动注册器,用于自动向consul注册配置
     */
    protected static class ConfigAutoRegisterConfiguration {

        @Value("${spring.application.name}")
        private String appNo;

        @Bean
        @ConditionalOnMissingBean(NacosConfigProperties.class)
        public NacosConfigProperties nacosConfigProperties(ApplicationContext context) {
            if (context.getParent() != null
                    && BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    context.getParent(), NacosConfigProperties.class).length > 0) {
                return BeanFactoryUtils.beanOfTypeIncludingAncestors(context.getParent(),
                        NacosConfigProperties.class);
            }
            return new NacosConfigProperties();
        }

        @Bean
        @ConditionalOnMissingBean(NacosConfigManager.class)
        public NacosConfigManager nacosConfigManager(
                NacosConfigProperties nacosConfigProperties) {
            return new NacosConfigManager(nacosConfigProperties);
        }

        /**
         * 配置类收集器
         *
         * @param configProperties
         * @return
         */
        @Bean
        @ConditionalOnMissingBean(ConfigClassCollector.class)
        public ConfigClassCollector nacosConfigClassCollector(NacosConfigProperties configProperties) {
            return StringUtils.isBlank(configProperties.getBasePackage()) ?
                    new ConfigClassCollector() : new ConfigClassCollector(configProperties.getBasePackage());
        }

        /**
         * 配置类解析器
         *
         * @param configClassCollector
         * @return
         */
        @Bean
        @ConditionalOnMissingBean(ConfigClassParser.class)
        public ConfigClassParser configClassParser(ConfigClassCollector configClassCollector) {
            return new ConfigClassParser(configClassCollector.getConfigClasses(), appNo);
        }

        /**
         * 配置类注册器
         *
         * @param configClassParser
         * @param nacosConfigManager
         * @return
         */
        @Bean
        @ConditionalOnMissingBean(NacosConfigAutoRegister.class)
        public NacosConfigAutoRegister nacosConfigAutoRegister(ConfigClassParser configClassParser, NacosConfigManager nacosConfigManager) {
            NacosConfigAutoRegister nacosConfigAutoRegister = new NacosConfigAutoRegister(configClassParser.getConfigDescriptorListList(), nacosConfigManager, appNo);
            nacosConfigAutoRegister.registe();
            return nacosConfigAutoRegister;
        }

        @Bean
        @ConditionalOnMissingBean(NacosPropertySourceLocator.class)
        public NacosPropertySourceLocator nacosPropertySourceLocator(ConfigClassParser configClassParser, NacosConfigAutoRegister configAutoRegister, NacosConfigProperties properties) {
            return new NacosPropertySourceLocator(configClassParser.getConfigDescriptorListList(), configAutoRegister, properties);
        }
    }


}
